dnl
dnl lib/usage/all.c template.
dnl
dnl Copyright (C) 2010 Nikolai Kondrashov
dnl
dnl This file is part of hidrd.
dnl
dnl Hidrd is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl Hidrd is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with hidrd; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
dnl
include(`m4/hidrd/util.m4')dnl
dnl
`/*
 * vim:nomodifiable
 *
 * ************* DO NOT EDIT **************
 * This file is autogenerated from all.c.m4
 * ****************************************
 */
/** @file
 * @brief HID report descriptor - all usages
 *
 * Copyright (C) 2010 Nikolai Kondrashov
 *
 * This file is part of hidrd.
 *
 * Hidrd is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Hidrd is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with hidrd; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @author Nikolai Kondrashov <spbnick@gmail.com>
 */

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "hidrd/cfg.h"
#include "hidrd/util/hex.h"
#include "hidrd/util/str.h"
#include "hidrd/util/tkn.h"
#include "hidrd/usage/id_desc_list.h"
#include "hidrd/usage/page_desc_list.h"
#include "hidrd/usage/all.h"

/* Define usage to string conversion functions */
HIDRD_NUM_CONV_DEFS(usage, u32)

/**
 * Lookup a usage ID description by a usage value.
 *
 * @param value The usage value.
 *
 * @return Usage ID description or NULL, if not found.
 */
static const hidrd_usage_id_desc *
lookup_id_desc(hidrd_usage usage)
{
    const hidrd_usage_page_desc    *desc;

    assert(hidrd_usage_valid(usage));

    desc = hidrd_usage_page_desc_list_lkp_by_value(
                                hidrd_usage_get_page(usage));

    return desc == NULL
            ? NULL
            : hidrd_usage_id_desc_list_lkp_by_value(
                                        desc->id_list, desc->id_num,
                                        hidrd_usage_get_id(usage));
}


bool
hidrd_usage_valid(hidrd_usage usage)
{
    hidrd_usage min = HIDRD_USAGE_MIN;
    hidrd_usage max = HIDRD_USAGE_MAX;

    return (usage >= min) && (usage <= max);
}


bool
hidrd_usage_known(hidrd_usage usage)
{
    return lookup_id_desc(usage) != NULL;
}


#ifdef HIDRD_WITH_TOKENS
char *
hidrd_usage_to_token(hidrd_usage usage)
{
    const hidrd_usage_page_desc    *page_desc;
    const hidrd_usage_id_desc      *id_desc;
    char                           *token;

    assert(hidrd_usage_valid(usage));

    page_desc = hidrd_usage_page_desc_list_lkp_by_value(
                                        hidrd_usage_get_page(usage));
    if (page_desc == NULL)
        return NULL;
    id_desc = hidrd_usage_id_desc_list_lkp_by_value(
                                        page_desc->id_list,
                                        page_desc->id_num,
                                        hidrd_usage_get_id(usage));
    if (id_desc == NULL)
        return NULL;

    if (asprintf(&token, "%s_%s", page_desc->token, id_desc->token) < 0)
        return NULL;

    return token;
}


char *
hidrd_usage_to_id_token(hidrd_usage usage)
{
    const hidrd_usage_id_desc  *desc;

    assert(hidrd_usage_valid(usage));

    desc = lookup_id_desc(usage);
    if (desc == NULL)
        return NULL;

    return strdup(desc->token);
}


bool
hidrd_usage_from_token(hidrd_usage *pusage, const char *token)
{
    const hidrd_usage_page_desc    *p = hidrd_usage_page_desc_list;
    size_t                          i = sizeof(hidrd_usage_page_desc_list) /
                                        sizeof(*hidrd_usage_page_desc_list);

    size_t      token_len;
    const char *page_token;
    size_t      page_token_len;

    assert(hidrd_tkn_valid(token));

    token_len = strlen(token);

    for (; i > 0; i--, p++)
    {
        page_token = p->token;
        page_token_len = strlen(p->token);

        if (page_token_len < token_len &&
            token[page_token_len] == 'dnl
changequote([,])['_']changequote(`,')` &&
            strncasecmp(token, page_token, page_token_len) == 0)
        {
            const hidrd_usage_id_desc  *id_desc;

            id_desc = hidrd_usage_id_desc_list_lkp_by_token(
                        p->id_list, p->id_num,
                        token + page_token_len + 1);

            if (id_desc == NULL)
                return false;

            if (pusage != NULL)
                *pusage = hidrd_usage_compose(p->value, id_desc->value);

            return true;
        }
    }

    return false;
}
#endif /* HIDRD_WITH_TOKENS */


#ifdef HIDRD_WITH_NAMES
const char *
hidrd_usage_id_name(hidrd_usage usage)
{
    const hidrd_usage_id_desc  *desc;

    assert(hidrd_usage_valid(usage));

    desc = lookup_id_desc(usage);

    return (desc != NULL) ? desc->name : NULL;
}

char *
hidrd_usage_desc_id_str(hidrd_usage usage)
{
    char                       *result          = NULL;
    const hidrd_usage_id_desc  *desc;
    char                       *shex            = NULL;
    char                       *type_set_desc   = NULL;

    assert(hidrd_usage_valid(usage));

    desc = lookup_id_desc(usage);
    if (desc == NULL)
        return strdup("");

    shex = hidrd_usage_id_to_shex(hidrd_usage_get_id(usage));
    if (shex == NULL)
        goto cleanup;

    type_set_desc = hidrd_usage_type_set_desc_str(desc->type_set);
    if (type_set_desc == NULL)
        goto cleanup;

    if (asprintf(&result,
'changequote([,])[
                 (*type_set_desc == '\0') ? "%s (%s)%.0s" : "%s (%s, %s)",
]changequote(`,')`
                 desc->name, shex, type_set_desc) < 0)
    {
        result = NULL;
        goto cleanup;
    }

cleanup:

    free(type_set_desc);
    free(shex);

    return result;
}


char *
hidrd_usage_desc_str(hidrd_usage usage)
{
    char    *result      = NULL;
    char    *usage_desc  = NULL;
    char    *page_desc   = NULL;

    assert(hidrd_usage_valid(usage));

    usage_desc = hidrd_usage_desc_id_str(usage);
    if (usage_desc == NULL)
        goto cleanup;
    page_desc = hidrd_usage_page_desc_str(hidrd_usage_get_page(usage));
    if (page_desc == NULL)
        goto cleanup;

'changequote([,])[
    if (*usage_desc == '\0')
    {
        result = page_desc;
        page_desc = NULL;
    }
    else if (*page_desc == '\0')
    {
        result = usage_desc;
        usage_desc = NULL;
    }
    else
    {
        if (asprintf(&result, "%s - %s", usage_desc, page_desc) < 0)
        {
            result = NULL;
            goto cleanup;
        }
    }
]changequote(`,')`

cleanup:

    free(page_desc);
    free(usage_desc);

    return result;
}
#endif /* HIDRD_WITH_NAMES */

'dnl
